package com.beyondsoft.common.activiti.support;

import com.beyondsoft.common.activiti.exception.ActivitiException;
import com.beyondsoft.common.activiti.exception.ResultCode;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;

/**
 * @author zhangyan
 * @version $ Id: StartProcessInstanceSupport.java, v 0.1 2020/6/20 11:47 zhangyan Exp $
 */
@Component
public class StartProcessInstanceSupport {

    @Resource
    private ProcessEngine processEngine;

    public String start(String authenticateUserId, String processDefinitionKey,
                        String processDefinitionId, String businessKey,
                        Map<String, Object> variables) {
        String processInstanceId;
        try {
            if (StringUtils.isNotBlank(authenticateUserId)) {
                this.processEngine.getIdentityService().setAuthenticatedUserId(authenticateUserId);
            }
            ProcessInstance processInstance;
            if (StringUtils.isNotBlank(processDefinitionKey)) {
                if (StringUtils.isNotBlank(businessKey)) {
                    if (CollectionUtils.isEmpty(variables)) {
                        processInstance = this.processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey, businessKey);
                    } else {
                        processInstance = this.processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
                    }
                } else if (CollectionUtils.isEmpty(variables)) {
                    processInstance = this.processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey);
                } else {
                    processInstance = this.processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey, variables);
                }
            } else {
                if (!StringUtils.isNotBlank(processDefinitionId)) {
                    throw new ActivitiException(ResultCode.ILLEGAL_PARAM.getCode(), "流程启动key或Id为空");
                }

                if (StringUtils.isNotBlank(businessKey)) {
                    if (CollectionUtils.isEmpty(variables)) {
                        processInstance = this.processEngine.getRuntimeService().startProcessInstanceById(processDefinitionKey, businessKey);
                    } else {
                        processInstance = this.processEngine.getRuntimeService().startProcessInstanceById(processDefinitionKey, businessKey, variables);
                    }
                } else if (CollectionUtils.isEmpty(variables)) {
                    processInstance = this.processEngine.getRuntimeService().startProcessInstanceById(processDefinitionKey);
                } else {
                    processInstance = this.processEngine.getRuntimeService().startProcessInstanceById(processDefinitionKey, variables);
                }
            }

            if (Objects.isNull(processInstance)) {
                throw new ActivitiException(ResultCode.NO_DATA.getCode(), "流程启动异常");
            }
            processInstanceId = processInstance.getId();
        } catch (Exception e) {
            throw new ActivitiException(ResultCode.NO_DATA.getCode(), "流程启动异常");
        } finally {
            if (StringUtils.isNotBlank(authenticateUserId)) {
                this.processEngine.getIdentityService().setAuthenticatedUserId(null);
            }
        }
        return processInstanceId;
    }

    /**
     * 判断是否挂起状态
     *
     * @param procInstId 流程实例id
     * @return
     */
    public boolean isSuspended(String procInstId) {
        if (StringUtils.isBlank(procInstId)) {
            throw new ActivitiException(ResultCode.NO_DATA.getCode(), "流程实例编号不能为空");
        }
        boolean flag = true;
        ProcessInstance processInstance =
                processEngine.getRuntimeService()
                        .createProcessInstanceQuery()
                        .processInstanceId(procInstId)
                        .singleResult();
        if (!Objects.isNull(processInstance)) {
            flag = processInstance.isSuspended();
        }
        return flag;
    }

    /**
     * 挂起流程
     *
     * @param procInstId
     */
    public void suspendByProcessId(String procInstId) {
        processEngine.getRuntimeService().suspendProcessInstanceById(procInstId);
    }


    /**
     * 删除流程
     */
    public void deleteProcessInstance(String procInstId, String reason, String assignee) {
        Authentication.setAuthenticatedUserId(assignee);
        processEngine.getRuntimeService().deleteProcessInstance(procInstId, reason);
    }
}
